#include "stdafx.h"
#include "D3DXMesh.h"

namespace Framework {

D3DXMesh::D3DXMesh(ID3DXMesh* mesh) : mesh(mesh) {
    this->boundingBox = NULL;
    this->boundingSphere = NULL;
    this->materials = new vector<D3DMATERIAL9>();
    this->textures = new vector<IDirect3DBaseTexture9*>();
    this->CalculateBoundingGeometry();
}

D3DXMesh::~D3DXMesh(void) {
    if (this->boundingBox != NULL) {
        d3d::Delete(this->boundingBox);
    }

    if (this->boundingSphere != NULL) {
        d3d::Delete(this->boundingSphere);
    }

    d3d::Delete(this->materials);
    d3d::Delete(this->textures);
}

d3d::BoundingBox* D3DXMesh::GetBoundingBox() const {
    return this->boundingBox;
}

d3d::BoundingSphere* D3DXMesh::GetBoundingSphere() const {
    return this->boundingSphere;
}

vector<D3DMATERIAL9>* D3DXMesh::GetMaterials() const {
    return this->materials;
}

ID3DXMesh* D3DXMesh::GetMesh() const {
    return this->mesh;
}

vector<IDirect3DBaseTexture9*>* D3DXMesh::GetTextures() const {
    return this->textures;
}

void D3DXMesh::CalculateBoundingGeometry() {
    BYTE* v = 0;
    if (this->boundingBox != NULL) {
        d3d::Delete(this->boundingBox);
    }

    this->boundingBox = new d3d::BoundingBox();

    if (this->boundingSphere != NULL) {
        d3d::Delete(this->boundingSphere);
    }

    this->boundingSphere = new d3d::BoundingSphere();

    this->mesh->LockVertexBuffer(0, (void**)&v);

    D3DXComputeBoundingBox(
        (D3DXVECTOR3*)v,
        this->mesh->GetNumVertices(),
        D3DXGetFVFVertexSize(this->mesh->GetFVF()),
        &this->boundingBox->_min,
        &this->boundingBox->_max);

    D3DXComputeBoundingSphere(
        (D3DXVECTOR3*)v,
        this->mesh->GetNumVertices(),
        D3DXGetFVFVertexSize(this->mesh->GetFVF()),
        &this->boundingSphere->_center,
        &this->boundingSphere->_radius);

    mesh->UnlockVertexBuffer();

    D3DXVECTOR3 obb[8];
    obb[0] = D3DXVECTOR3(boundingBox->_min.x, boundingBox->_min.y, boundingBox->_min.z); // xyz
    obb[1] = D3DXVECTOR3(boundingBox->_max.x, boundingBox->_min.y, boundingBox->_min.z); // Xyz
    obb[2] = D3DXVECTOR3(boundingBox->_min.x, boundingBox->_max.y, boundingBox->_min.z); // xYz
    obb[3] = D3DXVECTOR3(boundingBox->_max.x, boundingBox->_max.y, boundingBox->_min.z); // XYz
    obb[4] = D3DXVECTOR3(boundingBox->_min.x, boundingBox->_min.y, boundingBox->_max.z); // xyZ
    obb[5] = D3DXVECTOR3(boundingBox->_max.x, boundingBox->_min.y, boundingBox->_max.z); // XyZ
    obb[6] = D3DXVECTOR3(boundingBox->_min.x, boundingBox->_max.y, boundingBox->_max.z); // xYZ
    obb[7] = D3DXVECTOR3(boundingBox->_max.x, boundingBox->_max.y, boundingBox->_max.z); // XYZ

    boundingBox->_min.x = boundingBox->_max.x = obb[0].x;
    boundingBox->_min.y = boundingBox->_max.y = obb[0].y;
    boundingBox->_min.z = boundingBox->_max.z = obb[0].z;

    for (int i=1;i<8;i++) {
        if (obb[i].x < boundingBox->_min.x) boundingBox->_min.x = obb[i].x;
        if (obb[i].x > boundingBox->_max.x) boundingBox->_max.x = obb[i].x;
        if (obb[i].y < boundingBox->_min.y) boundingBox->_min.y = obb[i].y;
        if (obb[i].y > boundingBox->_max.y) boundingBox->_max.y = obb[i].y;
        if (obb[i].z < boundingBox->_min.z) boundingBox->_min.z = obb[i].z;
        if (obb[i].z > boundingBox->_max.z) boundingBox->_max.z = obb[i].z;
    }
}

}
